﻿using System;
using Godot;

namespace GoGameClient.script.tool;

public static class Vector2Util
{
    public static string GetDirection(Vector2I currentPosition, Vector2I targetPosition)
    {
        // 计算向量
        var position = ((Vector2)currentPosition).DirectionTo(targetPosition);
        if (position.X >= 0 && position.X <= 0.3)
        {
            position.X = 0;
        }
        else if (position.X >= -0.3 && position.X <= 0)
        {
            position.X = 0;
        }
        
        if (position.Y >= 0 && position.Y <= 0.3)
        {
            position.Y = 0;
        }
        else if (position.Y >= -0.3 && position.Y <= 0)
        {
            position.Y = 0;
        }
        // 判断方向  
        return position switch
        {
            // 第二象限  右上
            { X: < 0, Y: > 0 } => "右上",
            // 第一象限  右上
            { X: > 0, Y: > 0 } => "左上",
            // 第四象限  左下
            { X: > 0, Y: < 0 } => "左下",
            // 第三象限  右下
            { X: < 0, Y: < 0 } => "右下",

            // y轴正方向  上
            { Y: > 0 } => "上",
            // y轴负方向  下
            { Y: < 0 } => "下",
            // x轴负方向  左
            { X: < 0 } => "右",
            // x轴正方向  右
            { X: > 0 } => "左",
            _ => null
        };
    }


    public static Vector2I PositionToMap(Vector2I vector2I)
    {
        vector2I.X /= 20;
        vector2I.Y /= 20;
        return vector2I;
    }

    public static Vector2I MapToPosition(Vector2I vector2I)
    {
        vector2I.X *= 20;
        vector2I.Y *= 20;
        return vector2I;
    }

    public static double GetLength(Vector2 currentPosition, Vector2 targetPosition)
    {
        return Math.Sqrt(
            Math.Pow(currentPosition.X - targetPosition.X, 2) +
            Math.Pow(currentPosition.Y - targetPosition.Y, 2));
    }

    private static double Angle(Vector2 currentPosition, Vector2 targetPosition)
    {
        if (targetPosition == new Vector2I(0, 0))
        {
            return 0;
        }

        if (currentPosition == targetPosition)
        {
            return 0;
        }

        if (currentPosition.Y <= targetPosition.Y && targetPosition.X <= currentPosition.X)
        {
            return Math.PI -
                   Math.Abs(Math.Atan((targetPosition.Y - currentPosition.Y) / (targetPosition.X - currentPosition.X)));
        }

        if (targetPosition.Y <= currentPosition.Y && currentPosition.X <= targetPosition.X)
        {
            return Math.PI * 2 -
                   Math.Abs(Math.Atan((targetPosition.Y - currentPosition.Y) / (targetPosition.X - currentPosition.X)));
        }

        if (targetPosition.Y <= currentPosition.Y && targetPosition.X <= currentPosition.X)
        {
            return Math.Atan((targetPosition.Y - currentPosition.Y) / (targetPosition.X - currentPosition.X)) + Math.PI;
        }

        return Math.Atan((targetPosition.Y - currentPosition.Y) / (targetPosition.X - currentPosition.X));
    }

    public static Vector2 GetToPosition(Vector2 currentPosition, Vector2 targetPosition, double length)
    {
        var angle = Angle(currentPosition, targetPosition);
        return new Vector2I(
            (int)Math.Floor(length * (float)Math.Cos(angle) + currentPosition.X),
            (int)Math.Floor(length * (float)Math.Sin(angle) + currentPosition.Y));
    }

    public static Vector2 GetToPosition(Vector2 currentPosition, double length, double angle)
    {
        return new Vector2I(
            (int)Math.Floor(length * (float)Math.Cos(angle) + currentPosition.X),
            (int)Math.Floor(length * (float)Math.Sin(angle) + currentPosition.Y));
    }
}